package com.itttq.tools.mybatis.core;

import com.itttq.tools.mybatis.to.GeneratorTo;
import com.itttq.tools.mybatis.to.ProjectTo;
import com.itttq.tools.mybatis.util.StringUtil;
import freemarker.template.Configuration;
import freemarker.template.Template;

import java.io.*;
import java.util.List;

/**
 * 使用Freemarker模板生成文件
 *
 * @author Administrator
 */
public class GenerateProject {
    /**
     * 生成的Java文件父目录，会在下面创建mapper、model/po目录
     * 模板文件位置
     */
    public static String tmplProjectFlord = "D:/workspace/code/java/self/itttq-tools/tools-mybatis/docs/tmpls/project/";
    public static String tmplGeneratorFlord = "D:/workspace/code/java/self/itttq-tools/tools-mybatis/docs/tmpls/generator/";
    /**
     * 项目父路径
     */
    public static final String parentDir = "D:/workspace/code/Java/self/generator/";
    public static final String JAVA_DIR = "src/main/java/";
    public static final String NAME_APPLICATION = "Application.java";
    public static final String NAME_MAPPER = "Mapper.java";
    /**
     * 占位符，会在实际生成文件过程中被替换为实体类名称
     */
    public static final String PLACEHOLDER = "@@@";

    public static void main(String[] args) throws IOException {
        genByProjectDir();
    }

    /**
     * 循环读取只需要项目配置就能生成的文件
     * @param project   项目配置信息
     * @param conf      模板配置信息
     * @param file      文件或文件目录
     * @throws IOException
     */
    public static void genByProjectDir(ProjectTo project, Configuration conf, File file) throws IOException {
        String tmplPath;
        String filePath;
        for (File f : file.listFiles()) {
            if (f.isDirectory()) {
                genByProjectDir(project, conf, f);
            } else {
                tmplPath = f.getCanonicalPath().replaceAll("\\\\", "/").replace(tmplProjectFlord, "");
                filePath = tmplPath.replace(JAVA_DIR, JAVA_DIR + project.getPackagePath().replaceAll("\\.", TableInfo.SLASH) + TableInfo.SLASH);
                if (NAME_APPLICATION.equals(f.getName())) {
                    filePath = filePath.replace(NAME_APPLICATION, StringUtil.capitalize(project.getCode()) + NAME_APPLICATION);
                }
                generateByProjectTo(project, conf.getTemplate(tmplPath), parentDir + filePath);
            }
        }
    }

    /**
     * 循环读取只需要项目配置就能生成的文件
     * @param project   项目配置信息
     * @param conf      模板配置信息
     * @param file      文件或文件目录
     * @throws IOException
     */
    public static void genByGeneratorDir(ProjectTo project, List<GeneratorTo> generators, Configuration conf, File file) throws IOException {
        String tmplPath;
        String filePath;
        for (File f : file.listFiles()) {
            if (f.isDirectory()) {
                genByGeneratorDir(project, generators, conf, f);
            } else {
                tmplPath = f.getCanonicalPath().replaceAll("\\\\", "/").replace(tmplGeneratorFlord, "");
                filePath = tmplPath.replace(JAVA_DIR, JAVA_DIR + project.getPackagePath().replaceAll("\\.", TableInfo.SLASH) + TableInfo.SLASH);
                if(NAME_MAPPER.equals(f.getName())) {
                    filePath = filePath.replace(f.getName(), "I"+PLACEHOLDER + f.getName());
                } else {
                    filePath = filePath.replace(f.getName(), PLACEHOLDER + f.getName());
                }
                generateByGenerators(generators, conf.getTemplate(tmplPath), parentDir + filePath);
            }
        }
    }

    public static void genByProjectDir() throws IOException {
        ProjectTo project = getProjectConfig();
        List<GeneratorTo> generators = TableInfo.getTableInfo(project);
        if (generators.isEmpty()) {
            return;
        }

        Configuration configuration = new Configuration(Configuration.VERSION_2_3_21);
        GeneratorTo generator = generators.get(0);
        // 代码目录路径：如 src/main/java/
        File tmplDir = new File(tmplProjectFlord);
        configuration.setDirectoryForTemplateLoading(tmplDir);
        genByProjectDir(project, configuration, tmplDir);

        tmplDir = new File(tmplGeneratorFlord);
        configuration.setDirectoryForTemplateLoading(tmplDir);
        genByGeneratorDir(project, generators, configuration, tmplDir);
    }

    private static ProjectTo getProjectConfig() {
        ProjectTo.ProjectToBuilder projectToBuilder = ProjectTo.builder();
        projectToBuilder.code("generator").packagePath("com.itttq.generator").description("SSM项目生成器，自动生成SpringBoot + SpringMVC + Mybatis Plus")
                .name("SSM项目生成器").dbHost("127.0.0.1").dbPort("3306").dbName("generator").dbUserName("root").dbPassword("123456");
        return projectToBuilder.build();
    }

    /**
     * 根据ProjectTo对象生成文件
     *
     * @param project 项目对象
     * @param tmpl    模板对象
     * @param path    生成文件路径
     * @return 生成成功返回true，生成失败返回false
     */
    public static boolean generateByProjectTo(ProjectTo project, Template tmpl, String path) {
        StringWriter stringWriter = null;
        boolean rs = true;
        try {
            stringWriter = new StringWriter();
            tmpl.process(project, stringWriter);
            // 生成Po文件
            createFile(stringWriter.toString(), path);
        } catch (Exception e) {
            e.printStackTrace();
            rs = false;
        } finally {
            closeStringWriter(stringWriter);
        }
        return rs;
    }


    /**
     * 根据GeneratorTo集合生成文件
     *
     * @param generators Generator对象
     * @param tmpl       模板对象
     * @param path       生成文件路径
     * @return 生成成功返回true，生成失败返回false
     */
    public static boolean generateByGenerators(List<GeneratorTo> generators, Template tmpl, String path) {
        StringWriter out = null;
        boolean rs = true;
        for (GeneratorTo generator : generators) {
            try {
                out = new StringWriter();
                tmpl.process(generator, out);
                // 生成Po文件
                createFile(out.toString(), path.replace(PLACEHOLDER, StringUtil.capitalize(generator.getAlias())));
            } catch (Exception e) {
                e.printStackTrace();
                rs = false;
                break;
            } finally {
                closeStringWriter(out);
            }
        }
        return rs;
    }

    private static void closeStringWriter(StringWriter stringWriter) {
        try {
            if (null != stringWriter) {
                stringWriter.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void createFile(String content, String filePath) throws Exception {
        System.out.println(filePath);
        if (filePath.contains(TableInfo.DOT)) {
            //得到写文件路径
            File file = new File(filePath.substring(0, filePath.lastIndexOf(TableInfo.SLASH)));
            //如果目录不存在，则创建目录
            if (!file.exists()) {
                file.mkdirs();
            }
        }
        //写文件
        OutputStreamWriter out = null;
        try {
            out = new OutputStreamWriter(new FileOutputStream(filePath), "utf-8");
            out.write(content);
            out.flush();
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }

}
